package com.teamone.etl.dataruleengine.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.teamone.etl.dataruleengine.dao.RuleEngineDao;
import com.teamone.etl.dataruleengine.dto.RuleEngineReq;
import com.teamone.etl.dataruleengine.entity.RuleEngine;
import com.teamone.etl.dataruleengine.service.RuleEngineService;
import com.teamone.etl.util.CreateFileUtil;
import com.teamone.etl.util.ScriptRunnerExecSql;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import static com.teamone.etl.constant.EtlConstant.RuleEngine.FOLDER;
import static com.teamone.etl.constant.EtlConstant.TypeConstant.CODE_TYPE_JAVA;
import static com.teamone.etl.constant.EtlConstant.TypeConstant.CODE_TYPE_SQL;

/**
 * (RuleEngine)表服务实现类
 *
 * @author makejava
 * @since 2021-01-12 21:04:40
 */
@Service("ruleEngineService")
@Transactional(rollbackFor = Exception.class)
public class RuleEngineServiceImpl extends ServiceImpl<RuleEngineDao, RuleEngine> implements RuleEngineService {
    @Resource
    private RuleEngineDao ruleEngineDao;

    /**
     * 添加规则
     * @param ruleEngine
     * @return
     * @throws IOException
     */
    @Override
    public boolean addRuleEngine(RuleEngine ruleEngine) throws IOException {
        //判断类/函数名称是否存在（唯一效验）
        RuleEngine functionName = ruleEngineDao.getFunctionName(ruleEngine.getFunctionName());
        if(functionName != null) {
            return false;
        }else{
            //判断functionName类型，1：java   2：sql
            if(CODE_TYPE_JAVA.equals(ruleEngine.getCodeTypeId())){
                //判断文件夹是否存在  FOLDER为当前文件路径
                File file = new File(FOLDER+"rule");
                if(!file.exists()){
                    file.mkdir();
                }
                //生成.java文件路径
                CreateFileUtil.getJavaFile(ruleEngine.getFunctionName());
                //初始化文件信息
                String codes = CreateFileUtil.initializeFile(ruleEngine.getFunctionName());
                ruleEngine.setCodes(codes);
            }else if(CODE_TYPE_SQL.equals(ruleEngine.getCodeTypeId())){
                //判断文件夹是否存在   FOLDER为当前文件路径
                File file = new File(FOLDER+"database");
                if(!file.exists()){
                    file.mkdir();
                }
                CreateFileUtil.getSqlFile(ruleEngine.getFunctionName());
            }else{
                return false;
            }
            ruleEngine.setIsDisable(0);
            ruleEngine.setCreateTime(new Date());
            ruleEngine.setUpdateTime(new Date());
            ruleEngineDao.addRuleEngine(ruleEngine);
            return true;
        }


    }

    /**
     * 执行相应文件
     * @param ruleEngine
     * @return
     */
    @Override
    public boolean execute(RuleEngine ruleEngine) throws IOException {
        //根据id获得当前对象
        RuleEngine re = ruleEngineDao.getRuleEngineById(ruleEngine.getId());
        try {
            //获取本地当前项目路径和要存入的路径
            File file = CreateFileUtil.getSqlFile(re.getFunctionName());
            //创建字符输出流对象，向文件中写入
            FileWriter fileWriter = new FileWriter(file);
            //把将要执行的sql写入当前.sql文件中
            fileWriter.write(ruleEngine.getCodes());
            if (fileWriter != null) {
                try {
                    //若fileWriter不为空，关闭fileWriter
                    fileWriter.close();
                    //传入当前文件名称，调用执行.sql文件返回结果
                    boolean b = ScriptRunnerExecSql.execute(re.getFunctionName());
                    ruleEngineDao.updateCodes(ruleEngine);
                    return b;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
    /**
     * 编译java代码
     * @param ruleEngine    规则引擎对象
     * @param codes         新更改的代码
     * @return              是否编译/运行成功
     * @throws IOException  创建文件异常
     */
    @Override
    public boolean compileJava(RuleEngine ruleEngine, String codes) throws IOException {
        //运行代码
        CreateFileUtil.updateFile(ruleEngine.getFunctionName(), codes);
        //更新代码到数据库中的codes字段
        ruleEngine.setCodes(codes);
        ruleEngineDao.updateCodes(ruleEngine);
        return true;
    }
    /**
     * 模糊分页查询
     *
     * @param codeTypeId    规则类型id
     * @param name          规则名称
     * @param functionName  类/函数名称
     * @param page          当前页
     * @param size          每页显示条数
     * @return 部分数据
     */
    @Override
    public PageInfo<RuleEngine> ruleSearch(String codeTypeId, String name, String functionName, Integer page, Integer size) {
        //最大查询100条
        size = (size > 100) ? 100 : size;
        //分页实现
        PageHelper.startPage(page, size);
        List<RuleEngine> search = ruleEngineDao.ruleSearch(codeTypeId, name, functionName);
        return new PageInfo<>(search);
    }

    /**
     *修改
     *
     * @param ruleEngineReq 规则引擎对象
     */
    @Override
    public Boolean updateRuleEngine(RuleEngineReq ruleEngineReq) {

        //判断名字是否重复
        int i = baseMapper.getFunctionNameCountAndNotMe(ruleEngineReq.getId(),ruleEngineReq.getName());

        if(i>0) {
            return false;
        }
        //判断传输是否为空
        if(ruleEngineReq.getId() != null && ruleEngineReq.getIsDisable() !=null && !("").equals(ruleEngineReq.getName())) {
            //创建实体 并赋值
            RuleEngine ruleEngine = new RuleEngine();
            ruleEngine.setId(ruleEngineReq.getId());
            ruleEngine.setName(ruleEngineReq.getName());
            ruleEngine.setIsDisable(ruleEngineReq.getIsDisable());
            ruleEngine.setUpdateTime(new Date());
            baseMapper.updateRuleEngine(ruleEngine);
            return true;
        }
        return false;
    }

    /**
     * 回显
     *
     * @param id 主键
     * @return  规则引擎对象
     */
    @Override
    public RuleEngine getRuleEngineById(Integer id) {
        return baseMapper.getRuleEngineById(id);
    }

    /**
     * 逻辑删除
     *
     * @param id 主键
     */
    @Override
    public void delRuleEngineById(Integer id) throws IOException {
        //通过id查数据
        RuleEngine rule = ruleEngineDao.getRuleEngineById(id);


        // 判断是否为java文件
        if(CODE_TYPE_JAVA.equals(rule.getCodeTypeId())) {
            File javaFile =CreateFileUtil.getJavaFile(rule.getFunctionName());
            File clazzFile =CreateFileUtil.getClassFile(rule.getFunctionName());
            //执行System.gc()函数的作用只是提醒或告诉虚拟机，希望进z行一次垃圾回收。
            System.gc();

            //删除文件
            if (javaFile.delete() && clazzFile.delete()){
                System.out.println("Successfully deleted: " + javaFile);
                System.out.println("Successfully deleted: " + clazzFile);
            }else{
                System.out.println("Unable to delete: " + javaFile);
                System.out.println("Unable to delete: " + clazzFile);
            }

        }
        // 判断是否为sql文件
        if(CODE_TYPE_SQL.equals(rule.getCodeTypeId())) {
            File file = CreateFileUtil.getSqlFile(rule.getFunctionName());
            //执行System.gc()函数的作用只是提醒或告诉虚拟机，希望进行一次垃圾回收。
            System.gc();

            if(file.delete()) {
                System.out.println("Successfully deleted: " + file);
            }else {
                System.out.println("Unable to delete: " + file);
            }
        }

        baseMapper.delRuleEngineById(id,new Date());
    }

}